/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
 
class MyPromise{
  constructor (executor){
      try {
          //立即执行函数
          executor(this.resove,this.reject)
      } catch (error) {
          this.reject(error)
      }
  }
  //状态
  status = PADDING
  //成功之后的值
  value = undefined
  //失败后的原因
  reason = undefined
  //成功回调
  successCallback = []
  //失败回调
  failCallback = []
  
  
  resove = value =>{
      //如果状态不是padding 就不能再修改状态了 组织程序向下执行
      if(this.status != PADDING) return
      //将状态更改为成功
      this.status = FUFILLED
      this.value = value
      // this.successCallback && this.successCallback(this.value)
      while(this.successCallback.length) this.successCallback.shift()() 
  }
  reject = reason =>{
      if(this.status != PADDING) return
      //将状态更改为失败
      this.status = REJECTED
      this.reason = reason
      // this.failCallback && this.failCallback(this.reason)
      while(this.failCallback.length) this.failCallback.shift()() 
  }
  then = (successCallback,failCallback) =>{
      successCallback = successCallback ? successCallback : value => value
      failCallback = failCallback ? failCallback : reason => { throw reason }
      let myPromise  = new MyPromise((resove,reject)=>{
          //立即执行器  会立即执行
          if(this.status == FUFILLED){
              setTimeout(() => {
                  try {
                      let x =  successCallback(this.value);
                      //1.判断x的值是普通值还是promise对象
                      //2.如果是promise对象 查看promise对象返回的结果
                      //3.再根据promise对象返回的结果，决定调用resolve 还是调用reject
                      resovePromise(myPromise,x,resove,reject)
                  } catch (error) {
                      reject(error)
                  }
              }, 0);
          }
          else if(this.status == REJECTED){
              setTimeout(() => {
                  try {
                      let x =  failCallback(this.reason);
                      //1.判断x的值是普通值还是promise对象
                      //2.如果是promise对象 查看promise对象返回的结果
                      //3.再根据promise对象返回的结果，决定调用resolve 还是调用reject
                      resovePromise(myPromise,x,resove,reject)
                  } catch (error) {
                      reject(error)
                  }
              }, 0);
          }else{
              this.successCallback.push(()=>{
                  setTimeout(() => {
                      try {
                          let x =  successCallback(this.value);
                          //1.判断x的值是普通值还是promise对象
                          //2.如果是promise对象 查看promise对象返回的结果
                          //3.再根据promise对象返回的结果，决定调用resolve 还是调用reject
                          resovePromise(myPromise,x,resove,reject)
                      } catch (error) {
                          reject(error)
                      }
                  }, 0);
              })
              this.failCallback.push(()=>{
                  setTimeout(() => {
                      try {
                          let x =  failCallback(this.reason);
                          //1.判断x的值是普通值还是promise对象
                          //2.如果是promise对象 查看promise对象返回的结果
                          //3.再根据promise对象返回的结果，决定调用resolve 还是调用reject
                          resovePromise(myPromise,x,resove,reject)
                      } catch (error) {
                          reject(error)
                      }
                  }, 0);
              }) 
          }
      })
      
      return myPromise
  }
  finally(callback){//处理异步的问题
     return this.then((value)=>{
        return MyPromise.resolve(callback()).then(() => value)
      },(reason)=>{
          return MyPromise.resolve(callback()).then(() =>{throw reason} )
      })
  }
  catch(failCallback){
      this.then(undefined,failCallback)
  }
  static all = (array)=>{//
      let result = []
      let index = 0//解决index的问题
      return new MyPromise((resove,reject)=>{
          function addData(key,value){
              result[key] = value
              index++
              if(index == array.length){
                  resove(result)//等待异步操作的结果
              }
          }
          for(let i=0;i<array.length;i++){//for循环没有执行异步操作
              let current = array[i];
              if(current instanceof MyPromise){
                  current.then(value => addData(i,value),reason => reject(reason))
              }else{
                  addData(i,current)
              }
          }
      })
  }
  static resolve = (value) => {
      if(value instanceof MyPromise) return value
      return new MyPromise((resove,reject)=>{
          resove(value)
      })
  }
};

function resovePromise(myPromise,x,resove,reject){
  if(myPromise === x ){
      return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if(x instanceof MyPromise){
      x.then(resove,reject)
  }else{
     resove(x) 
  }
}
module.exports = MyPromise